
#include	<cstring>
#include	<cstdlib>

#include	"zig/url.hpp"

namespace	zig
{

	URL::URL(const std::string& url) 
		: m_url(url), m_port(0)
	{
		this->parse( url );
	}


	/** Parse the URL.
	 *
	 * Parse the URL into the protocol, the hostname, the path and the paramters with their values
	 */
	void URL::parse (const std::string& url) 
	{
		/* format example		
		 * protocol://hostname:port/path/path/path.pl?param1=value1&amp;param2=value2
		 * we include the script name in the path, so the path would be /path/path/path.pl in this example
		 *  &amp; could also be &
		 */

		//1. Init
		const char* urlPtr = url.c_str();
		int pos = 0;

		m_protocol = "";
		m_hostname = "";
		m_path = "";
		m_query = "";
		m_anchor = "";

		// 2. Get the protocol, which is from the begining to the first ://
		bool checkHostname = true;
		const char* end = strchr( urlPtr, ':' );
		if (end) { //protocol was found
			m_protocol.append(urlPtr, end-urlPtr);
			urlPtr = end + 1;

			//find the end of the protocol separator (e.g. "://")
			////for (; (*urlPtr == ':') || (*urlPtr == '/'); urlPtr++);
			urlPtr++, urlPtr++;	// for "://"
			if ('/' == *urlPtr) {
				// for "file:///tmp/abc.txt"
				checkHostname = false;
			}
		}

		//3.Get the hostname part. This is the part from pos up to the first slash
		bool checkPath   = true;
		bool checkParams = true;
		bool checkAnchor = true;

		end = strchr(urlPtr, '/');
		if (!end) {
			checkPath = false;
			end = strchr(urlPtr, '?');
		}
		if (!end) {
			checkParams = false;
			end = strchr(urlPtr, '#');
		}
		if (!end) {
			checkAnchor = false;
			end = urlPtr+strlen(urlPtr);
		}

		if (checkHostname) {
			const char*	_end_hostname = strchr(urlPtr, ':');
			if (!_end_hostname) {
				m_hostname.append(urlPtr, end-urlPtr);
			}
			else {
				m_hostname.append(urlPtr, _end_hostname - urlPtr);
				m_port = atoi(_end_hostname + 1);
			}

			urlPtr = end + ((*end)? 1 : 0);
		}

		if (checkPath) {
			// path should begin with '/'
			while( '/' != *urlPtr ) --urlPtr;

			end = strchr(urlPtr, '?');
			if (!end) {
				checkParams = false;
				end = strchr(urlPtr, '#');
			}
			if (!end) {
				checkAnchor = false;
				end = urlPtr+strlen(urlPtr);
			}

			m_path.append(urlPtr, end-urlPtr);

			urlPtr = end + ((*end)? 1 : 0);
		}

		if (checkParams) {
			end = strchr(urlPtr, '#');
			if (!end) {
				checkAnchor = false;
				end = urlPtr+strlen(urlPtr);
			}

			m_query.append(urlPtr, end - urlPtr);

			urlPtr = end + ((*end) ? 1 : 0);
		}

		if (checkAnchor) {
			m_anchor.append( urlPtr );
		}
	}	// parse()

}	// namespace zig

